package zwyarraylist;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

import org.junit.BeforeClass;
import org.junit.Test;

/**
* modCount详解
* @ClassName: ArrayList02Test 
* @Description: TODO
* @author zhaoweiyong  yyd 
* @date 2017年6月23日 下午3:11:12 *
 */
public class ArrayList02Test {
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	* 176-181行测试
	public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = Arrays.copyOf(elementData, size);
        }
    }
	*public void trimToSize()
	* @title: test
	* @throws NoSuchFieldException
	* @throws SecurityException
	* @throws IllegalAccessException 
	* @Author: zhaoweiyong
	* @Date: 2017年6月23日下午12:58:11
	 */
	@Test
	public void testTrimToSize() throws NoSuchFieldException, SecurityException, IllegalAccessException {
		ArrayList<String> dataList = new ArrayList<String>(10);
		dataList.add("1");
		Field modCountField = dataList.getClass().getSuperclass().getDeclaredField("modCount");
		modCountField.setAccessible(true);
		Object modCount = modCountField.get(dataList);
		System.out.println("进行了"+modCount+"次操作！");
		
		Field elementDataField = dataList.getClass().getDeclaredField("elementData");
		elementDataField.setAccessible(true);
		Object[] elementData = (Object[]) elementDataField.get(dataList);
		System.out.println("原始的数组的大小："+elementData.length);
		dataList.trimToSize();
		elementData = (Object[]) elementDataField.get(dataList);
		System.out.println("压缩后的数组的大小："+elementData.length);
		modCount = modCountField.get(dataList);
		System.out.println("进行了"+modCount+"次操作！");
	}
	
	
	//modCount登场 
	//进而引入CopyOnWriteArrayList
	//list 通过跌带起迭代的时候是不可以修改的
	//但是可以通过迭代器修改
	//java.util.ConcurrentModificationException
	//Iterator
	@Test
	public void testModCount() throws Exception{
		ArrayList<String> list = new ArrayList<String>();
	    //CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
	    list.add("a");
	    list.add("b");
	    list.add("c");
	    list.add("d");
	    list.add("e");
	    Field modCountField = list.getClass().getSuperclass().getDeclaredField("modCount");
		modCountField.setAccessible(true);
		Object modCount = modCountField.get(list);
		System.out.println("进行了"+modCount+"次操作！");
	    Iterator<String> iterator = list.iterator();
	    modCount = modCountField.get(list);
		System.out.println("进行了"+modCount+"次操作！");
	    try {
			while(iterator.hasNext()){
				Field expectedModCountField = iterator.getClass().getDeclaredField("expectedModCount");
				expectedModCountField.setAccessible(true);
				Object expectedModCount = expectedModCountField.get(iterator);
				modCount = modCountField.get(list);
				System.out.println("期望进行了"+expectedModCount+"次操作！实际是："+ modCount);
			    String str = (String) iterator.next();
			    if(str.equals("c")){
			        list.remove(str);
			        modCount = modCountField.get(list);
					System.out.println("进行了第"+modCount+"次操作！");
			    }else{
			        System.out.println(str);
			    }
			}
		} catch (Exception e) {
			System.err.println("className:" + e.getClass().getName());
		}
	    System.out.println("-------------------------------------------------------------");
	    System.out.println("-------------------------------------------------------------");
	    System.out.println("-------------------------------------------------------------");
	    System.out.println("进行了"+modCount+"次操作！");
	    iterator = list.iterator();
	    while(iterator.hasNext()){
			Field expectedModCountField = iterator.getClass().getDeclaredField("expectedModCount");
			expectedModCountField.setAccessible(true);
			Object expectedModCount = expectedModCountField.get(iterator);
			modCount = modCountField.get(list);
			System.out.println("期望进行了"+expectedModCount+"次操作！实际是："+ modCount);
		    String str = (String) iterator.next();
		    if(str.equals("b")){   
		    	iterator.remove();
		        modCount = modCountField.get(list);
				System.out.println("进行了第"+modCount+"次操作！");
		    }else{
		        System.out.println(str);
		    }
		}
	}
	
	/**
	  fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时，就可能会产生fail-fast事件。例如：当某一个线程A通过iterator去遍历某集合的过程中，若该集合的内容被其他线程所改变了；那么线程A访问集合时，就会抛出ConcurrentModificationException异常，产生fail-fast事件。
	      要了解fail-fast机制，我们首先要对ConcurrentModificationException 异常有所了解。当方法检测到对象的并发修改，但不允许这种修改时就抛出该异常。同时需要注意的是，该异常不会始终指出对象已经由不同线程并发修改，如果单线程违反了规则，同样也有可能会抛出改异常。
	     诚然，迭代器的快速失败行为无法得到保证，它不能保证一定会出现该错误，但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常，所以因此，为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法，正确做法是：ConcurrentModificationException 应该仅用于检测 bug。
	* @title: testModCount2
	* @throws Exception 
	* @Author: zhaoweiyong
	* @Date: 2017年6月23日下午2:12:30
	 */
	@Test
	public void testModCount2() throws Exception{
		final ArrayList<String> list = new ArrayList<String>();
	    list.add("a");
	    list.add("b");
	    list.add("c");
	    list.add("d");
	    list.add("e");
	    
	    
	    new Thread(){
	    	@Override
	    	public void run() {
	    		while(true){
	    			list.add("f");
		    		list.add("g");
	    		}
	    	}
	    }.start();
	    Field modCountField = list.getClass().getSuperclass().getDeclaredField("modCount");
		modCountField.setAccessible(true);
	    Iterator<String> iterator = list.iterator();
	    while(iterator.hasNext()){
			Field expectedModCountField = iterator.getClass().getDeclaredField("expectedModCount");
			expectedModCountField.setAccessible(true);
			Object expectedModCount = expectedModCountField.get(iterator);
			Object modCount = modCountField.get(list);
			System.out.println("期望进行了"+expectedModCount+"次操作！实际是："+ modCount);
		    String str = (String) iterator.next();
		    System.out.println(str);
		}
	}
	
	@Test
	public void testCopyOnWriteArrayList(){
		CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
	    list.add("a");
	    list.add("b");
	    list.add("c");
	    list.add("d");
	    list.add("e");
	    Iterator<String> iterator = list.iterator();
	    while(iterator.hasNext()){
		    String str = (String) iterator.next();
		    if(str.equals("c")){
		        list.remove(str);
		    }else{
		        System.out.println(str);
		    }
		}
	}
	
	//数组的复制和操作以及压缩
	@Test
	public void testCopyArray() {
		Integer[] originArr = new Integer[] { 1, 2, 3 };
		Object[] dest = new Object[2];
		System.arraycopy(originArr, 1, dest, 0, 2);
		for(Object obj : dest){
			System.out.println(obj);
		}
		
		System.arraycopy(originArr, 0, dest, 0, 2);
		for(Object obj : dest){
			System.out.println(obj);
		}
	}
}
